home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-16 | 16.8 KB | 544 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: ScrollEd.cpp
- // Release Version: $ ODF 1 $
- //
- // Author: Laurent Delamare
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "Form.hpp"
-
- #ifndef SCROLLED_H
- #include "ScrollEd.h"
- #endif
-
- #ifndef FRAME_H
- #include "Frame.h"
- #endif
-
- #ifndef EDITCMD_H
- #include "EditCmd.h"
- #endif
-
- #ifndef FWPART_H
- #include "FWPart.h"
- #endif
-
- #ifndef FWEVENT_H
- #include "FWEvent.h"
- #endif
-
- #ifndef FWEVEDEF_H
- #include "FWEveDef.h"
- #endif
-
- #ifndef FWSCLBAR_H
- #include "FWSclBar.h"
- #endif
-
- #ifndef FWSCLNOT_H
- #include "FWSclNot.h"
- #endif
-
- #ifndef FWCONTXT_H
- #include "FWContxt.h"
- #endif
-
- //========================================================================================
- // RunTime Info
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment odfform
- #endif
-
- FW_DEFINE_CLASS_M3(CScrollEdit, FW_CEditView, FW_MReceiver, FW_MNotifier);
- FW_DEFINE_AUTO(CScrollEdit)
-
- const FW_ClassTypeConstant LScrollEd = FW_TYPE_CONSTANT('S','e','d','v');
- FW_REGISTER_ARCHIVABLE_CLASS(LScrollEd, CScrollEdit, CScrollEdit::Create, FW_CView::Read, CScrollEdit::Destroy, FW_CView::Write)
-
- //========================================================================================
- // CScrollEdit
- //========================================================================================
-
- // Documentation
- // -------------
- // CScrollEdit adds scrolling functionalities to FW_CEditView and adds support for
- // Undo/Redo clipboard commands
- //
- // CScrollEdit inherits from FW_MReceiver in order to respond to scrolling notifications
- //
- // CScrollEdit must disable its clipboard commands when the
- // view is deleted (see discussion in CEditViewCommand::HandleNotification)
- //
- // A CScrollEdit object requires a vertical and/or an horizontal scrollbars.
- // It can be created from resources, see the type RScrollEdit in Form's views.fr
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::CScrollEdit
- //----------------------------------------------------------------------------------------
-
- CScrollEdit::CScrollEdit (Environment* ev,
- FW_CSuperView* container,
- ODID viewId,
- const FW_CRect& bounds,
- FW_CScrollBar* horzSB,
- FW_CScrollBar* vertSB,
- const FW_CString& str,
- const FW_CFont& font,
- short maxChars,
- unsigned short attributes,
- FW_Fixed textWidth)
- : FW_CEditView(ev, container, viewId, bounds, str, font, maxChars, attributes),
- FW_MReceiver()
- {
- fScrollbars[FW_kHorizontal] = horzSB;
- fScrollbars[FW_kVertical] = vertSB;
-
- // use the view width by default
- fWidth = (textWidth == FW_kFixed0) ? bounds.Size().x : textWidth;
-
- Initialize(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::CScrollEdit
- //----------------------------------------------------------------------------------------
- CScrollEdit::CScrollEdit(Environment* ev)
- : FW_CEditView(ev),
- FW_MReceiver()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::Initialize
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::Initialize(Environment* ev)
- {
- // scrolling view responds to scrollbar notifications
- if (fScrollbars[FW_kVertical])
- AddInterest(FW_CInterest(fScrollbars[FW_kVertical], FW_kScrollMsg));
-
- if (fScrollbars[FW_kHorizontal])
- AddInterest(FW_CInterest(fScrollbars[FW_kHorizontal], FW_kScrollMsg));
-
- AdjustTERects(ev);
- UpdateScrollParameters(ev);
- UpdateScrollUnits(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::~CScrollEdit
- //----------------------------------------------------------------------------------------
-
- CScrollEdit::~CScrollEdit ()
- {
- // Don't delete the scroll bars, we don't own them!
-
- if (fScrollbars[FW_kHorizontal])
- {
- FW_CInterest interest(fScrollbars[FW_kHorizontal], FW_kScrollMsg);
- RemoveInterest(interest);
- }
- if (fScrollbars[FW_kVertical])
- {
- FW_CInterest interest(fScrollbars[FW_kVertical], FW_kScrollMsg);
- RemoveInterest(interest);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::AdjustTERects
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::AdjustTERects(Environment* ev)
- {
- TEHandle teHdl = (TEHandle)GetPlatformEditHandle(ev);
- TEPtr te = *teHdl;
-
- // Set viewRect height to a multiple of lines to avoid cutting lines
- te->viewRect.bottom = (((te->viewRect.bottom - te->viewRect.top) / te->lineHeight)
- * te->lineHeight) + te->viewRect.top;
-
- // Adjust width of destination rectangle for text scrolling horizontally
- if (fScrollbars[FW_kHorizontal])
- te->destRect.right = te->destRect.left + FW_FixedToInt(fWidth);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::SizeChanged
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::SizeChanged (Environment* ev, const FW_CPoint& oldSize)
- {
- // call base class to update the TEd viewRect
- FW_CEditView::SizeChanged(ev, oldSize);
-
- AdjustTERects(ev);
-
- // We use the fact that the scrollbars have already been resized because they
- // were created before the CScrollEdit object.
- UpdateScrollParameters(ev);
- UpdateScrollUnits(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::UpdateScrollUnits
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::UpdateScrollUnits(Environment* ev)
- {
- TEHandle teHdl = (TEHandle)GetPlatformEditHandle(ev);
- FW_CScrollBar* sb = fScrollbars[FW_kHorizontal];
-
- if (sb)
- {
- short major = (**teHdl).viewRect.right - (**teHdl).viewRect.left;
- short minor = major / 10;
- sb->SetMinorScrollUnits(ev, FW_IntToFixed(minor));
- sb->SetMajorScrollUnits(ev, FW_IntToFixed(major));
- }
-
- sb = fScrollbars[FW_kVertical];
- if (sb)
- {
- short major = ((**teHdl).viewRect.bottom - (**teHdl).viewRect.top) / (**teHdl).lineHeight;
- sb->SetMajorScrollUnits(ev, FW_IntToFixed(major));
- // minor scroll unit is always 1 line.
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::UpdateScrollParameters
- //----------------------------------------------------------------------------------------
- void CScrollEdit::UpdateScrollParameters(Environment* ev)
- {
- AdjustScrollbar(ev, FW_kVertical);
- AdjustScrollbar(ev, FW_kHorizontal);
-
- // Must also scroll the Ted to match up the new scrollbar values
- // in case a scroll bar became inactive and the Ted was already scrolled
- AdjustTE(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::AdjustTE
- //----------------------------------------------------------------------------------------
- void CScrollEdit::AdjustTE(Environment* ev)
- {
- // We must create a graphic context and adjust the Mac text-edit
- // before making any native TE calls
- FW_CViewContext gc (ev, this, GetFrame(ev)->GetActiveFacet(ev));
- MacAdjustRects (ev, gc);
-
- TEHandle teHdl = (TEHandle)GetPlatformEditHandle(ev);
-
- FW_CScrollBar* sb = fScrollbars[FW_kHorizontal];
- short hScroll = 0;
- if (sb)
- hScroll = ((**teHdl).viewRect.left - (**teHdl).destRect.left) - FW_FixedToInt(sb->GetScrollPos(ev));
-
- sb = fScrollbars[FW_kVertical];
- short vScroll = 0;
- if (sb)
- vScroll = ((**teHdl).viewRect.top - (**teHdl).destRect.top) -
- (FW_FixedToInt(sb->GetScrollPos(ev)) * ((**teHdl).lineHeight));
-
- TEScroll(hScroll, vScroll, teHdl);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::AdjustScrollbar
- //----------------------------------------------------------------------------------------
- // Code borrowed from the MPW example TEDocument.cp
-
- void CScrollEdit::AdjustScrollbar(Environment* ev, FW_XYSelector direction)
- {
- FW_CScrollBar* sb = fScrollbars[direction];
- if (sb == NULL)
- return;
-
- TEHandle teHdl = (TEHandle)GetPlatformEditHandle(ev);
- TEPtr te = *teHdl;
- int max = 0;
- int oldMax = FW_FixedToInt(sb->GetScrollMax(ev));
-
- if (direction == FW_kVertical)
- {
- short lines = te->nLines;
- // add 1 line if last char is a return
- if ( *(*te->hText + te->teLength - 1) == 13 )
- lines += 1;
- max = lines - (( te->viewRect.bottom - te->viewRect.top ) / te->lineHeight);
- }
- else
- {
- max = FW_FixedToInt(fWidth) - ( te->viewRect.right - te->viewRect.left );
- }
-
- if (max < 0) max = 0;
-
- // Must convert to fixed number for SetScrollMax
- sb->SetScrollMax(ev, FW_IntToFixed(max));
-
- te = *teHdl;
- int value;
- int oldValue = FW_FixedToInt(sb->GetScrollPos(ev));
-
- if (direction == FW_kVertical)
- value = ( te->viewRect.top - te->destRect.top ) / te->lineHeight;
- else
- value = te->viewRect.left - te->destRect.left;
-
- if (value < 0)
- value = 0;
- else if (value > max)
- value = max;
-
- // Must convert to fixed number for SetScrollPos
- sb->SetScrollPos(ev, FW_IntToFixed(value));
-
- if (value == oldValue && max != oldMax)
- sb->RedrawControl(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::DoAdjustMenus
- //----------------------------------------------------------------------------------------
-
- FW_Boolean CScrollEdit::DoAdjustMenus (Environment *ev, FW_CMenuBar* menuBar,
- FW_Boolean hasMenuFocus, FW_Boolean isRoot)
- {
- // Let base class adjust the Edit menu first
- FW_CEditView::DoAdjustMenus(ev, menuBar, hasMenuFocus, isRoot);
-
- if (hasMenuFocus)
- {
- // update the Paste command
- FW_Boolean hasClipboard = GetFrame(ev)->HasPropertyOnClipboard(ev, kODPropContents, FW_CPart::gMacTEXTDataType);
- menuBar->EnableCommand (ev, kODCommandPaste, hasClipboard);
- }
- return FALSE; // let parent views adjust their menus
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::DoMenu
- //----------------------------------------------------------------------------------------
-
- FW_Boolean CScrollEdit::DoMenu (Environment* ev, const FW_CMenuEvent& event)
- {
- ODCommandID id = event.GetCommandID(ev);
- FW_Boolean commandHandled = true;
-
- switch (id)
- {
- case kODCommandCut:
- case kODCommandCopy:
- case kODCommandPaste:
- case kODCommandClear:
- // Ask the frame to create an EditView command:
- // if the command is created, execute it
- // if the frame didn't implement NewClipboardCommand(), revert to default behavior
- CEditViewCommand* cmd = (CEditViewCommand*)GetFrame(ev)->NewClipboardCommand(ev, id);
- if (cmd)
- {
- cmd->SetEditView(this);
- if (cmd->GetSelection(ev) == NULL)
- {
- // The presentation doesn't have any selection, we create one on the fly
- cmd->SetSelection(FW_NEW(CEditViewSelection, (ev, this)));
- }
- cmd->Execute(ev);
- }
- else
- {
- DoTECommand(ev, id, true); // Will use normal scrap
- }
- UpdateScrollParameters(ev);
- break;
-
- default:
- commandHandled = FW_CEditView::DoMenu (ev, event); // call base class
-
- if (id == kODCommandSelectAll)
- UpdateScrollParameters(ev);
- }
- return commandHandled;
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::HandleNotification
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::HandleNotification(Environment* ev, const FW_CNotification& notification)
- {
- if (notification.GetMessage() == FW_kScrollMsg)
- {
- const FW_CScrollNotification& scrollNfy = (FW_CScrollNotification&) notification;
-
- FW_XYSelector direction = scrollNfy.GetDirection(ev);
- int amount = FW_FixedToInt(-scrollNfy.GetDelta(ev));
-
- if (amount != 0)
- {
- TEHandle teHdl = (TEHandle)GetPlatformEditHandle(ev);
-
- // We must create a graphic context and adjust the Mac text-edit
- // before making any native TE calls
- FW_CViewContext gc (ev, this, GetFrame(ev)->GetActiveFacet(ev));
- MacAdjustRects (ev, gc);
-
- if (direction == FW_kVertical)
- TEScroll(0, amount * (*teHdl)->lineHeight, teHdl);
- else
- TEScroll(amount, 0, teHdl);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::DoVirtualKey
- //----------------------------------------------------------------------------------------
-
- FW_Boolean CScrollEdit::DoVirtualKey (Environment* ev, const FW_CVirtualKeyEvent & event)
- {
- // Let base class handle the key first
- FW_Boolean keyHandled = FW_CEditView::DoVirtualKey(ev, event);
-
- short keyCode = event.GetKeyCode(ev);
-
- // Handle PageUp and PageDown keys
- if (keyHandled == false && (keyCode == FW_kVKPageUp || keyCode == FW_kVKPageDown))
- {
- TEHandle teHdl = (TEHandle)GetPlatformEditHandle(ev);
- short amount = ((**teHdl).viewRect.bottom - (**teHdl).viewRect.top);
- if (keyCode == FW_kVKPageDown)
- amount = - amount;
-
- FW_CViewContext gc (ev, this, GetFrame(ev)->GetActiveFacet(ev));
- MacAdjustRects (ev, gc);
-
- TEScroll(0, amount, teHdl);
-
- keyHandled = true;
- UpdateScrollParameters(ev);
- }
-
- return keyHandled;
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::DoCharKey
- //----------------------------------------------------------------------------------------
-
- FW_Boolean CScrollEdit::DoCharKey (Environment* ev, const FW_CCharKeyEvent& event)
- {
- // Let base class handle the character first
- FW_Boolean handled = FW_CEditView::DoCharKey(ev, event);
-
- // Update scrollbars
- if (handled)
- UpdateScrollParameters(ev);
-
- return handled;
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::DoMouseDown
- //----------------------------------------------------------------------------------------
-
- FW_Boolean CScrollEdit::DoMouseDown (Environment* ev, const FW_CMouseEvent& event)
- {
- FW_Boolean handled = FW_CEditView::DoMouseDown(ev, event);
-
- // Adjust the scrollbars here after auto-scrolling may have occured
- UpdateScrollParameters(ev);
-
- return handled;
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::SetText
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::SetText (Environment * ev, const FW_CString& str)
- {
- FW_CEditView::SetText(ev, str);
- UpdateScrollParameters(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::Create
- //----------------------------------------------------------------------------------------
-
- void* CScrollEdit::Create(FW_CReadableStream& stream, FW_ClassTypeConstant type)
- {
- FW_UNUSED(stream);
- FW_UNUSED(type);
- FW_SOMEnvironment ev;
- return FW_NEW(CScrollEdit, (ev));
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::Destroy
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::Destroy(void* object, FW_ClassTypeConstant type)
- {
- FW_UNUSED(type);
- CScrollEdit* self = (CScrollEdit*) object;
- delete self;
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::Flatten
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::Flatten(Environment* ev, FW_CWritableStream& stream) const
- {
- FW_CEditView::Flatten(ev, stream);
-
- ODID horizScrollBarID = (fScrollbars[FW_kHorizontal] == NULL) ? kODNULLID :
- fScrollbars[FW_kHorizontal]->GetViewId(ev);
- ODID vertScrollBarID = (fScrollbars[FW_kVertical] == NULL) ? kODNULLID :
- fScrollbars[FW_kVertical]->GetViewId(ev);
-
- stream << horizScrollBarID << vertScrollBarID << fWidth;
- }
-
- //----------------------------------------------------------------------------------------
- // CScrollEdit::InitializeFromStream
- //----------------------------------------------------------------------------------------
-
- void CScrollEdit::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
- {
- FW_CEditView::InitializeFromStream(ev, stream);
-
- ODID horizScrollBarID;
- ODID vertScrollBarID;
- stream >> horizScrollBarID >> vertScrollBarID >> fWidth;
-
- FW_CSuperView* parentView = GetSuperView(ev);
- FW_ASSERT(parentView);
-
- FW_CView* hScrollBarView = NULL;
- if (horizScrollBarID != kODNULLID)
- hScrollBarView = parentView->FindViewById(ev, horizScrollBarID);
-
- FW_CView* vScrollBarView = NULL;
- if (vertScrollBarID != kODNULLID)
- vScrollBarView = parentView->FindViewById(ev, vertScrollBarID);
-
- fScrollbars[FW_kHorizontal] = FW_DYNAMIC_CAST(FW_CScrollBar, hScrollBarView);
- fScrollbars[FW_kVertical] = FW_DYNAMIC_CAST(FW_CScrollBar, vScrollBarView);
-
- Initialize(ev);
- }
-
-
-